﻿Imports MindFusion.Diagramming
Imports MindFusion.Drawing

Public Class ClsMMTableNode
    Inherits TableNode
    'represents my own diagram tablenode

#Region "Attributes"
#Region "Private attributes"
    Private MbIsSupportTable As Boolean = False  'is table support table?
#End Region
#End Region
#Region "Constructors"
    Public Sub New(ByVal parent As MindFusion.Diagramming.Diagram)
        MyBase.New(parent)
        MMSetDefaultProperties()
    End Sub

    Protected Sub New(ByVal prototype As MindFusion.Diagramming.DiagramItem)
        MyBase.New(prototype)
    End Sub

    Protected Sub New(ByVal prototype As MindFusion.Diagramming.DiagramNode)
        MyBase.New(prototype)
    End Sub

    Public Sub New(ByVal prototype As MindFusion.Diagramming.TableNode)
        MyBase.New(prototype)
    End Sub

    Public Sub New(ByVal IiX As Integer, ByVal IiY As Integer, ByVal IiWidth As Integer, ByVal IiHeight As Integer)
        MyBase.New()
        MMSetDefaultProperties()
        MyBase.Bounds = SDRectangleVirginCreator(IiX, IiY, IiWidth, IiHeight)
    End Sub
#End Region
#Region "Properties"
#Region "Public attributes"
    Public ReadOnly Property MMRectangleForNewLink() As RectangleF
        Get
            Return SDRectangleFVirginCreator(Me.Bounds.Right - 12, Me.Bounds.Top + 2, 10, Me.CaptionHeight - 2)
        End Get
    End Property
    Public Property MMIsSupportTable() As Boolean
        Get
            Return MbIsSupportTable
        End Get
        Set(ByVal IbValue As Boolean)
            MbIsSupportTable = IbValue
            Me.Brush = MMGetBrushForTable()
        End Set
    End Property
#End Region
#End Region
#Region "Subs"
#Region "Overrides & Overloads Subs"
    'overrided sub for saving to XML
    Protected Overrides Sub SaveToXml(ByVal xmlElement As System.Xml.XmlElement, ByVal context As MindFusion.Diagramming.XmlPersistContext)
        MyBase.SaveToXml(xmlElement, context)
        context.WriteEnum(Int(MMIsSupportTable), "IsSupportTable", xmlElement)
    End Sub
    'overrided sub for loading from XML
    Protected Overrides Sub LoadFromXml(ByVal xmlElement As System.Xml.XmlElement, ByVal context As MindFusion.Diagramming.XmlPersistContext)
        MyBase.LoadFromXml(xmlElement, context)
        'assigning values directly to variables not to property to prevent changing attributes after deserialization!
        MbIsSupportTable = context.ReadEnum("IsSupportTable", xmlElement)
    End Sub
    'overrided sub for drawing a table
    Public Overrides Sub Draw(ByVal graphics As MindFusion.Drawing.IGraphics, ByVal options As MindFusion.Diagramming.RenderOptions)
        MyBase.Draw(graphics, options)

        'drawing triangle for note indication
        DrawNoteTriangle(Me, graphics)
    End Sub
    'overrided sub for drawing handles
    Public Overrides Sub DrawHandles(ByVal graphics As MindFusion.Drawing.IGraphics, ByVal color As System.Drawing.Color)
        'Debug.Print("DrawHandles")

        ''drawing image and area for creating new link
        'Dim LoPoint As PointF = SDPointFVirginCreator(MMRectangleForNewLink.Right - 7, MMRectangleForNewLink.Y)
        'LoPoint = MainForm.fcDiagramView.ClientToDoc(MainForm.fcDiagramView.DocToClient(LoPoint))
        'graphics.DrawImage(MainForm.imlTableIcons.Images(7), LoPoint.X, LoPoint.Y)

        'graphics.DrawLine(SDPenVirginCreator(Drawing.Color.Gray, 0.5), MMRectangleForNewLink.X, MMRectangleForNewLink.Y, MMRectangleForNewLink.X, MMRectangleForNewLink.Y + MMRectangleForNewLink.Height)
        'graphics.DrawLine(SDPenVirginCreator(Drawing.Color.Gray, 0.5), MMRectangleForNewLink.X, MMRectangleForNewLink.Y, MMRectangleForNewLink.X + MMRectangleForNewLink.Width, MMRectangleForNewLink.Y)
        'graphics.DrawLine(SDPenVirginCreator(Drawing.Color.Gray, 0.5), MMRectangleForNewLink.X + MMRectangleForNewLink.Width, MMRectangleForNewLink.Y, MMRectangleForNewLink.X + MMRectangleForNewLink.Width, MMRectangleForNewLink.Y + MMRectangleForNewLink.Height)

        Const LdbWidthOfLineForRectangle As Double = 0.5

        'drawing filled rectangle
        Dim LoBrush As System.Drawing.Drawing2D.HatchBrush = New System.Drawing.Drawing2D.HatchBrush(Drawing2D.HatchStyle.LightUpwardDiagonal, Drawing.Color.Black, Drawing.Color.LightCoral)
        Dim LoRectangleF As RectangleF = New RectangleF(MMRectangleForNewLink.X, MMRectangleForNewLink.Y, MMRectangleForNewLink.Width, MMRectangleForNewLink.Height - IIf(Me.Pen.Width = 0, MindFusion.Diagramming.Constants.GetPixel(Me.Parent.MeasureUnit), Me.Pen.Width) / 2)
        graphics.FillRectangle(LoBrush, LoRectangleF)

        'drawing rectangle around filled rectangle
        Dim LoPen As System.Drawing.Pen = New System.Drawing.Pen(color.Gray, LdbWidthOfLineForRectangle)
        LoPen.DashStyle = Drawing2D.DashStyle.Solid
        'Dim LoRectangle As Rectangle = New Rectangle(LoRectangleF.X, LoRectangleF.Y, LoRectangleF.Width, LoRectangleF.Height )
        LoRectangleF.Height -= IIf(Me.Pen.Width = 0, MindFusion.Diagramming.Constants.GetPixel(Me.Parent.MeasureUnit), Me.Pen.Width) / 2
        graphics.DrawRectangles(LoPen, New RectangleF() {LoRectangleF})

        'drawing selection rectangle
        Const LdbWidthOfLine As Double = 0.7
        graphics.DrawRectangle(SDPenVirginCreator(color, LdbWidthOfLine), CType(Me.Bounds.X - LdbWidthOfLine / 2, Single), CType(Me.Bounds.Y - LdbWidthOfLine / 2, Single), CType(Me.Bounds.Width + LdbWidthOfLine, Single), CType(Me.Bounds.Height + LdbWidthOfLine, Single))
    End Sub
    'overrided sub called after deserialization of node. I can set some properties forcible here!
    Protected Overrides Sub OnLoad()
        MyBase.OnLoad()
    End Sub
#End Region
#Region "MM Subs"
    'default settings of shape
    Public Sub MMSetDefaultProperties()
        MMIsSupportTable = False 'brush is set here. Brush is used to fill the interiors of geometric shapes
        'minimum size is connected with minimum size of txtInPlaceEditor used for in-place editing
        Me.Constraints.MinHeight = 10
        Me.Constraints.MinWidth = 20
        'minimum size is connected with minimum size of txtInPlaceEditor used for in-place editing
        Me.HighlightedRow = -1 'sets the highlighted row to -1 = no row selected
        Me.Obstacle = True ' whether this node is considered an obstacle by the link-routing algorithm
        Me.Bounds = SDRectangleVirginCreator(0, 0, 50, 30)
        Me.EnableStyledText = False 'whether styled text rendering is enabled
        Me.Font = New Font("Arial", 8, FontStyle.Regular) 'font used to draw text inside this cell
        Me.OffsetHeaderRows = True 'whether the table cells are offset to the right to accommodate for the expand buttons of Header rows
        Me.AnchorPattern = CreateAnchorPatternSurrounding(9) 'Represents a set of anchor points, which specify the exact locations where links are allowed to connect to nodes
        Me.Pen = New Pen(Color.Gray) 'pen is used to draw the outline of geometric shapes
        Me.AllowIncomingLinks = True 'true - because of connections between tables and notes
        Me.AllowOutgoingLinks = True 'true - because of connections between tables
        Me.HandlesStyle = HandlesStyle.EasyMove 'visual styles for frames that are drawn around selected nodes
        Me.ShadowOffsetX = 0.5 'horizontal offset of the shadow
        Me.ShadowOffsetY = 0.5 'vertical offset of the shadow
        Me.CustomDraw = CustomDraw.Additional 'The custom painting code executes after item's interior and frame are painted by FlowChart.NET, but before text is rendered. In this mode, the Graphics instance passed to the custom drawing event handler has a clipping region applied to it
        Me.Style = TableStyle.RoundedRectangle 'the shape of the table's outline
        Me.ConnectionStyle = TableConnectionStyle.Table 'whether drawing a link from/to this table, should connect a row of the table, or the whole table as single ent
        Me.CellCustomDraw = MindFusion.Diagramming.CustomDraw.Additional 'type of custom drawing performed on the table cells - because I want to handle DrawCell event
        Me.RowHeight = 5 'the default height of table rows
        Me.RowCount = 0 ' the number of rows in the table
        Me.ColumnCount = 2 'the number of columns in the table
        Me.Columns(0).Width = 6 'width of the first column for icon
        Me.Columns(0).ColumnStyle = ColumnStyle.FixedWidth 'the manner in which column's width is set.
        Me.Columns(1).ColumnStyle = ColumnStyle.AutoWidth 'the manner in which column's width is set.
        Me.CellFrameStyle = CellFrameStyle.None 'the style of the cells' frame lines
        Me.ImageAlign = ImageAlign.MiddleRight 'the position and alignment of a picture relative to its destination rectangle
        Me.CaptionHeight = 6 'height of the table's caption area
        Me.CaptionFormat.Alignment = StringAlignment.Center 'alignment and line position of the text used as table caption
        Me.CaptionFormat.FormatFlags = StringFormatFlags.NoClip 'alignment and line position of the text used as table caption
        Me.CaptionFormat.Trimming = StringTrimming.None 'alignment and line position of the text used as table caption
        'Me.Caption = "<color=#2E7DA5>" & "<b>" & "Tabulka" & "</b>" & "</color>" 'the text displayed as caption of the table
        Me.Caption = GsStringDefaultValue    'the text displayed as caption of the table
        'Me.Scrollable = True
    End Sub
    'resizes heights of caption, all rows, whole table to fit text inside cells and to fit actual width of table and resizes parent container. Actual width of table is not changed!
    Public Sub MMResizeAllToFitTable(Optional ByVal IbRefreshParentContainer As Boolean = True)
        MMResizeHeightOfCellsToFitText()
        MMResizeHeightOfTableToFitCells()
        If IbRefreshParentContainer Then MMResizeParentContainer()
    End Sub
    'resizes heights of caption and all rows of the table to fit text inside them and to fit actual width of table. Actual width of table is not changed!
    Private Sub MMResizeHeightOfCellsToFitText()
        Debug.Print("MMResizeHeightOfCellsToFitText")

        Dim LnNewHeight As Single
        Dim LnWidth As Single

        'checking Me.Parent for MeasureUnit
        If Me.Parent Is Nothing Then
            Debug.Print("CHYBA!!! - MMResizeHeightOfCellsToFitText - Me.Parent = Nothing")
        End If

        'resizing height of caption
        'maxWidth parameter for MeasureString sub = actual width of caption
        LnWidth = Me.Bounds.Width

        LnNewHeight = Me.Parent.MeasureString(Me.Caption, Me.Font, LnWidth, Me.CaptionFormat).Height

        'setting a new height or keeping minimal height of caption
        Const LnMinimalCaptionHeight As Single = 6
        Me.CaptionHeight = IIf(LnNewHeight > LnMinimalCaptionHeight, LnNewHeight, LnMinimalCaptionHeight)
        'height of table will be at minimum as height of caption + default height of row
        Me.Constraints.MinHeight = Me.CaptionHeight + Me.RowHeight
        'need to set new height right now?
        If Me.Bounds.Height < Me.Constraints.MinHeight Then
            Me.Resize(Me.Bounds.Width, Me.Constraints.MinHeight)
        End If

        'resizing heights of all rows
        'maxWidth parameter for MeasureString sub = actual width of Columns(1)
        LnWidth = Me.Columns(1).Width
        For LiI As Integer = 0 To Me.RowCount - 1
            'calculating new height of row
            LnNewHeight = Me.Parent.MeasureString(Me(1, LiI).Text, Me.Font, LnWidth, Me(1, LiI).TextFormat).Height

            'setting a new height or keeping minimal height of rows (Me.RowHeight)
            Dim LnMinimalRowHeight As Single = Me.RowHeight
            Me.Rows(LiI).Height = IIf(LnNewHeight > LnMinimalRowHeight, LnNewHeight, LnMinimalRowHeight)
        Next
    End Sub
    'resizes height of whole table. Actual width of table is not changed!
    Private Sub MMResizeHeightOfTableToFitCells()
        'checking Me.Parent for MeasureUnit
        If Me.Parent Is Nothing Then
            Debug.Print("CHYBA!!! - MMResizeHeightOfTableToFitCells - Me.Parent =Nothing")
        End If

        Dim LiNewHeight As Integer = Me.CaptionHeight + 3 * IIf(Me.Pen.Width = 0, Constants.GetPixel(Me.Parent.MeasureUnit), Me.Pen.Width)
        '3 is for the top, bottom and caption divider lines. The cell borders should be included in the rows' Height and should not add to the height
        For Each LoRow As TableNode.Row In Me.Rows
            LiNewHeight += LoRow.Height
            Me.Resize(Me.Bounds.Width, LiNewHeight)
        Next
    End Sub
    'resizes parent container which table is in
    Private Sub MMResizeParentContainer()
        Dim LoMMContainerNode As ClsMMContainerNode = ContainerNode.GetContainer(Me)
        'If Me.MasterGroup IsNot Nothing AndAlso Me.MasterGroup.MainItem IsNot Nothing AndAlso Me.MasterGroup.MainItem.GetType.Name = "ClsMMContainerNode" Then
        '    CType(Me.MasterGroup.MainItem, ClsMMContainerNode).MMResizeAllToFitContainer()
        If LoMMContainerNode IsNot Nothing Then
            LoMMContainerNode.MMResizeAllToFitContainer()
        Else
            Debug.Print("CHYBA!!! - MMResizeParentContainer")
        End If
    End Sub
#End Region
#End Region
#Region "Functions"
#Region "Overrides & Overloads Functions"
    'inserting row to collection of columns and to table
    ' ''Public Overloads Function InsertRow(ByVal IePositionOfNewRow As GePositionOfNewRow, ByVal IiDataType As Integer, ByVal IsNameOfColumn As String, Optional ByVal IiNumberOfPositionOfNewRow As Integer = 0) As GeActionResult
    ' ''    Try
    ' ''        Dim LiPositionOfNewRow As Integer = 0
    ' ''        'what position?
    ' ''        Select Case IePositionOfNewRow
    ' ''            Case GePositionOfNewRow.kkFirst
    ' ''                LiPositionOfNewRow = 0
    ' ''            Case GePositionOfNewRow.kkLast
    ' ''                LiPositionOfNewRow = Me.RowCount
    ' ''            Case GePositionOfNewRow.kkSpecified
    ' ''                LiPositionOfNewRow = IiNumberOfPositionOfNewRow
    ' ''        End Select

    ' ''        If (LiPositionOfNewRow > Me.RowCount) Or (LiPositionOfNewRow < 0) Then
    ' ''            Debug.Print("CHYBA!!! - InsertRow")
    ' ''            Return GeActionResult.kkError
    ' ''        Else
    ' ''            'inserting table column to collection
    ' ''            ' ''If IsInCollection(MoColumns, IoTableColumn.NameOfColumn) Then
    ' ''            ' ''    Return GeActionResult.kkROWOFTABLEDuplicityOfNameOfRow
    ' ''            ' ''Else
    ' ''            ' ''    MoColumns.Add(IoTableColumn, IoTableColumn.NameOfColumn, LiPositionOfNewRow + 1)
    ' ''            ' ''End If

    ' ''            'inserting a new row into table
    ' ''            MyBase.InsertRow(LiPositionOfNewRow)
    ' ''            Me(1, LiPositionOfNewRow).TextFormat.Alignment = StringAlignment.Near
    ' ''            Me(1, LiPositionOfNewRow).TextFormat.FormatFlags = StringFormatFlags.NoClip
    ' ''            Me(1, LiPositionOfNewRow).TextFormat.Trimming = StringTrimming.None
    ' ''            Me(0, LiPositionOfNewRow).Image = MainForm.imlTableIcons.Images(IiDataType) 'IoTableColumn.DataType)
    ' ''            Me(1, LiPositionOfNewRow).Text = IsNameOfColumn 'IoTableColumn.NameOfColumn
    ' ''            Return GeActionResult.kkOk
    ' ''        End If
    ' ''    Catch ex As Exception
    ' ''        Return GeActionResult.kkError
    ' ''    End Try
    ' ''End Function
    '' ''deleting row from collection of columns and from table
    ' ''Public Overloads Function DeleteRow(ByVal IiPositionOfDeletedRow As Integer) As GeActionResult
    ' ''    Try
    ' ''        'deleting from collection
    ' ''        MoColumns.Remove(IiPositionOfDeletedRow + 1)
    ' ''        'deleting from table
    ' ''        MyBase.DeleteRow(IiPositionOfDeletedRow)
    ' ''        Return GeActionResult.kkOk
    ' ''    Catch ex As Exception
    ' ''        Return GeActionResult.kkError
    ' ''    End Try
    ' ''End Function
#End Region
#Region "MM Functions"
    'rebuild table (rows of tablenode) based on data from dataset
    Public Function MMRebuildTable(ByVal IoAmodFile As ClsFileAmod) As GeActionResult
        Dim LeResult As GeActionResult = GeActionResult.kkError

        Try
            Dim LsTableName As String = IoAmodFile.GetTableNameFromAppTableName(Me.Caption)
            Dim LoRows() As DataRow
            LoRows = IoAmodFile.Dataset.Tables("_a_Columns").Select("Tablename='" & LsTableName & "' AND _a_VID=" & IoAmodFile.ActualVID, "Position ASC")

            Debug.Print(Me.RowCount)

            Me.RowCount = 0
            For LiI As Integer = 0 To LoRows.Length - 1
                MyBase.InsertRow(LiI)
                Me(1, LiI).TextFormat.Alignment = StringAlignment.Near
                Me(1, LiI).TextFormat.FormatFlags = StringFormatFlags.NoClip
                Me(1, LiI).TextFormat.Trimming = StringTrimming.None
                Me(0, LiI).ImageAlign = MindFusion.Drawing.ImageAlign.Center
                Me(0, LiI).Image = MainForm.imlTableIcons.Images(GetIconIndexForTypeOfColumn(LoRows.ElementAt(LiI).Item("_a_ColumnType")))

                Me(1, LiI).Text = LoRows.ElementAt(LiI).Item("ColumnName")
            Next

            LeResult = GeActionResult.kkOk
        Catch ex As Exception
            Debug.Print("CHYBA!!! - MMRebuildTable")
            LeResult = GeActionResult.kkError
        End Try

        'resizing table and parent container
        MMResizeAllToFitTable()
        Return LeResult
    End Function
    'sets brush of table - if table is support table or not
    Private Function MMGetBrushForTable() As LinearGradientBrush
        Return IIf(Me.MbIsSupportTable, New LinearGradientBrush(Color.Thistle, Color.Plum, 90), New LinearGradientBrush(Color.White, Color.LightGreen, 90))
    End Function
    'gets collection of relationships links
    Public Function MMGetRelationshipsLinks(ByVal IbIncomingLinks As Boolean) As Collection
        Dim LoCollection As Collection = New Collection
        Dim LoDiagramLinkCollection As DiagramLinkCollection = IIf(IbIncomingLinks, Me.IncomingLinks, Me.OutgoingLinks)

        For Each LoMMLinkNode As ClsMMLinkNode In LoDiagramLinkCollection
            If LoMMLinkNode.MMTypeOfLink = GeTypeOfLink.kkRelationship Then LoCollection.Add(LoMMLinkNode)
        Next

        Return LoCollection
    End Function
    'gets number of relationships links specified type (incoming or outgoing)
    Public Function MMGetNumberOfRelationshipsLinks(ByVal IbIncomingLinks As Boolean) As Integer
        Dim LoDiagramLinkCollection As DiagramLinkCollection = IIf(IbIncomingLinks, Me.IncomingLinks, Me.OutgoingLinks)
        Dim LiResult As Integer = 0

        For Each LoMMLinkNode As ClsMMLinkNode In LoDiagramLinkCollection
            If LoMMLinkNode.MMTypeOfLink = GeTypeOfLink.kkRelationship Then LiResult += 1
        Next

        Return LiResult
    End Function
#End Region
#End Region

End Class
